home *** CD-ROM | disk | FTP | other *** search
- static char sccs_id[] = "@(#) mktime.c 3.0 "__DATE__" HJR";
-
- /* mktime.c (c) Copyright 1990 H.Rogers */
-
- #include <time.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
-
- static unsigned int __tmonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
-
- static struct tm __tz[1] = /* time struct */
- {
- { 0,0,0,0,0,0,0,0,-1,0,"" }
- };
-
- /* Time zones are "[TZNAME][H][:M][DSTNAME]" where H:M gives the time *west*
- * of GMT for the timezone. If DSTNAME appears then the time zone follows
- * DST rules according to DSTNAME. Examples:
- *
- * "EST5EDT" USA Eastern time zone
- * "CST6CDT" USA Central time zone
- * "NFLDT3:30NFLD" Newfoundland time (1:30 ahead of Eastern)
- * "OZCST-9:30" Australian Central time zone (no DST)
- *
- * DST is currently unimplemented: Other implementations involve very nasty
- * code in order to cater for exception years (e.g. USA 1972). Also most
- * assume USA rules for DST (which have changed 3 times since 1970), not UK
- * rules (which have changed more often and are more complex :-( ). It's
- * simpler to rely on the SysAdmin changing the system clock twice a year
- * according to local custom. Leap seconds and the century offset are ignored,
- * but the routines are correct to within a second till at least 2038... */
-
- int timezone = 0;
-
- void tzset(void)
- {
- char *z;
- register int i;
-
- if (!(z = getenv("TZ")))
- z = "GMT0UK"; /* default to GMT/UKDST */
-
- i = 0; while (isalpha(*z))
- {
- if (i < 3)
- { __tz->tm_zone[i] = *z; i++; }
- z++;
- }
- __tz->tm_zone[i] = 0;
-
- i = (int)strtol(z,&z,10) * 3600;
- if (*z == ':')
- { z++; i += (int)strtol(z,&z,10) * 60; }
-
- __tz->tm_gmtoff = timezone = i;
- }
-
- static struct tm *__mktm(register time_t);
-
- struct tm *gmtime(register const time_t *tp)
- {
- if (!(__tz->tm_zone[0])) tzset();
-
- return(__mktm(*tp));
- }
-
- struct tm *localtime(register const time_t *tp)
- {
- if (!(__tz->tm_zone[0])) tzset();
-
- return(__mktm((*tp) - __tz->tm_gmtoff));
- }
-
- static struct tm *__mktm(register time_t tm)
- {
- register struct tm *t = __tz;
- register time_t i,j,k;
-
- t->tm_isdst = -1;
-
- t->tm_wday = (tm / 86400 + 4) % 7; /* 1st Jan 1970 = Thursday */
-
- t->tm_sec = tm % 60; tm /= 60;
- t->tm_min = tm % 60; tm /= 60;
- t->tm_hour = tm % 24; tm /= 24;
-
- i = (365<<1); /* two years */
-
- if (tm >= i) /* >= 1972 */
- {
- j = (tm - i) / 1461;
- tm -= i + j * 1461;
- k = tm ? ((tm - 1) / 365) : 0;
- if (k)
- {
- tm -= 1 + k * 365;
- __tmonth[1] = 28;
- }
- else
- __tmonth[1] = 29; /* Feb. hath 29 days in a leap year */
- k += 2 + (j<<2);
- }
- else /* < 1972 */
- {
- k = tm / 365;
- tm -= k * 365;
- __tmonth[1] = 28;
- }
-
- t->tm_year = k + 70;
- t->tm_yday = tm;
-
- k = tm; j = 0; while(k >= (i = __tmonth[j])) k -= i,j++;
-
- t->tm_mon = j;
- t->tm_mday = k + 1;
-
- return(t);
- }
-
- time_t mktime(register struct tm *t)
- {
- register time_t r;
-
- if ((t->tm_year - 70) < 0) return((time_t)-1);
-
- r = t->tm_year - 70;
-
- if (r < 2)
- r = r * 365;
- else
- {
- register int i,j;
-
- i = (r - 2) & 3;
- j = ((r - 2)>>2) * 1461;
- if (i)
- {
- r = (365<<1) + j + 1 + i * 365;
- }
- else
- r = (365<<1) + j;
- }
-
- r += t->tm_yday;
- r = r * 24 + t->tm_hour;
- r = r * 60 + t->tm_min;
- r = r * 60 + t->tm_sec;
-
- r += t->tm_gmtoff; /* mktime() is passed a localtime() struct */
-
- return(r);
- }
-